package org.mybatis.generator.plugins.test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.tools.ant.util.DateUtils;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.GeneratedJavaScriptFile;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.OutputUtilities;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.JavaElement;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.internal.util.StringUtility;

/**
 * 生成controller类
 * 
 * 
 * super_dev_001
 */
public class MybatisTestPlugin extends PluginAdapter {

	private FullyQualifiedJavaType dateType;
	private FullyQualifiedJavaType serviceType;
	private FullyQualifiedJavaType pojoType;
	private FullyQualifiedJavaType qoType;
	private FullyQualifiedJavaType boType;
	private FullyQualifiedJavaType testType;
	private FullyQualifiedJavaType listType;
	private FullyQualifiedJavaType arrayListType;
	private FullyQualifiedJavaType autowired;

	private FullyQualifiedJavaType runWith;
	private FullyQualifiedJavaType methodSorters;
	private FullyQualifiedJavaType springJUnit4ClassRunner;
	private FullyQualifiedJavaType contextConfiguration;
	private FullyQualifiedJavaType fixMethodOrder;
	private FullyQualifiedJavaType test;

	private boolean enableCount = false;
	private boolean enableSelectByPrimaryKey = false;
	private boolean enableSelectByExample = false;
	private boolean enableSelectPageByExample = false;
	private boolean enableSelectAllByExample = false;
	private boolean enableSelectSimpleByExample = false;
	private boolean enableIsUniqueByExample = false;
	private boolean enableInsert = false;
	private boolean enableInsertSelective = false;
	private boolean enableDeleteByPrimaryKey = false;
	private boolean enableDeleteByExample = false;
	private boolean enableBatchDeleteByExample = false;
	private boolean enableUpdateByExample = false;
	private boolean enableUpdateByExampleSelective = false;
	private boolean enableUpdateByPrimaryKey = false;
	private boolean enableUpdateByPrimaryKeySelective = false;
	private boolean enableBatchUpdateByExample = false;

	private String targetPackage;
	private String servicePack;
	private String targetModel;
	private String serviceName;
	private String project;
	private String pojoUrl;

	private List<Method> methods;

	public MybatisTestPlugin() {
		super();
		dateType = new FullyQualifiedJavaType("java.util.Date");
		listType = new FullyQualifiedJavaType("java.util.List");
		arrayListType = new FullyQualifiedJavaType("java.util.ArrayList");
		methods = new ArrayList<Method>();
	}

	@Override
	public boolean validate(List<String> warnings) {

		targetPackage = properties.getProperty("targetPackage");
		targetModel = properties.getProperty("targetModel");
		servicePack = targetPackage + ".base.service." + targetModel;
		project = properties.getProperty("targetProject");
		pojoUrl = context.getJavaModelGeneratorConfiguration()
				.getTargetPackage();

		autowired = new FullyQualifiedJavaType(
				"org.springframework.beans.factory.annotation.Autowired");
		runWith = new FullyQualifiedJavaType("org.junit.runner.RunWith");
		fixMethodOrder = new FullyQualifiedJavaType("org.junit.FixMethodOrder");
		test = new FullyQualifiedJavaType("org.junit.Test");
		methodSorters = new FullyQualifiedJavaType(
				"org.junit.runners.MethodSorters");
		contextConfiguration = new FullyQualifiedJavaType(
				"org.springframework.test.context.ContextConfiguration");
		springJUnit4ClassRunner = new FullyQualifiedJavaType(
				"org.springframework.test.context.junit4.SpringJUnit4ClassRunner");

		String enableCount = properties.getProperty("enableCount");
		String enableSelectByPrimaryKey = properties
				.getProperty("enableSelectByPrimaryKey");
		String enableSelectByExample = properties
				.getProperty("enableSelectByExample");
		String enableSelectPageByExample = properties
				.getProperty("enableSelectPageByExample");
		String enableSelectSimpleByExample = properties
				.getProperty("enableSelectSimpleByExample");
		String enableSelectAllByExample = properties
				.getProperty("enableSelectAllByExample");
		String enableIsUniqueByExample = properties
				.getProperty("enableIsUniqueByExample");

		String enableInsert = properties.getProperty("enableInsert");

		String enableUpdateByExampleSelective = properties
				.getProperty("enableUpdateByExampleSelective");

		String enableInsertSelective = properties
				.getProperty("enableInsertSelective");

		String enableUpdateByPrimaryKey = properties
				.getProperty("enableUpdateByPrimaryKey");

		String enableDeleteByPrimaryKey = properties
				.getProperty("enableDeleteByPrimaryKey");

		String enableDeleteByExample = properties
				.getProperty("enableDeleteByExample");

		String enableBatchDeleteByExample = properties
				.getProperty("enableBatchDeleteByExample");

		String enableUpdateByPrimaryKeySelective = properties
				.getProperty("enableUpdateByPrimaryKeySelective");

		String enableUpdateByExample = properties
				.getProperty("enableUpdateByExample");
		String enableBatchUpdateByExample = properties
				.getProperty("enableBatchUpdateByExample");

		if (StringUtility.stringHasValue(enableCount))
			this.enableCount = StringUtility.isTrue(enableCount);
		if (StringUtility.stringHasValue(enableSelectByPrimaryKey))
			this.enableSelectByPrimaryKey = StringUtility
					.isTrue(enableSelectByPrimaryKey);
		if (StringUtility.stringHasValue(enableSelectByExample))
			this.enableSelectByExample = StringUtility
					.isTrue(enableSelectByExample);
		if (StringUtility.stringHasValue(enableSelectAllByExample))
			this.enableSelectAllByExample = StringUtility
					.isTrue(enableSelectAllByExample);
		if (StringUtility.stringHasValue(enableSelectPageByExample))
			this.enableSelectPageByExample = StringUtility
					.isTrue(enableSelectPageByExample);
		if (StringUtility.stringHasValue(enableSelectSimpleByExample))
			this.enableSelectSimpleByExample = StringUtility
					.isTrue(enableSelectSimpleByExample);
		if (StringUtility.stringHasValue(enableInsert))
			this.enableInsert = StringUtility.isTrue(enableInsert);
		if (StringUtility.stringHasValue(enableUpdateByExampleSelective))
			this.enableUpdateByExampleSelective = StringUtility
					.isTrue(enableUpdateByExampleSelective);
		if (StringUtility.stringHasValue(enableIsUniqueByExample))
			this.enableIsUniqueByExample = StringUtility
					.isTrue(enableIsUniqueByExample);
		if (StringUtility.stringHasValue(enableInsertSelective))
			this.enableInsertSelective = StringUtility
					.isTrue(enableInsertSelective);
		if (StringUtility.stringHasValue(enableUpdateByPrimaryKey))
			this.enableUpdateByPrimaryKey = StringUtility
					.isTrue(enableUpdateByPrimaryKey);
		if (StringUtility.stringHasValue(enableDeleteByPrimaryKey))
			this.enableDeleteByPrimaryKey = StringUtility
					.isTrue(enableDeleteByPrimaryKey);
		if (StringUtility.stringHasValue(enableDeleteByExample))
			this.enableDeleteByExample = StringUtility
					.isTrue(enableDeleteByExample);
		if (StringUtility.stringHasValue(enableBatchDeleteByExample))
			this.enableBatchDeleteByExample = StringUtility
					.isTrue(enableBatchDeleteByExample);
		if (StringUtility.stringHasValue(enableUpdateByPrimaryKeySelective))
			this.enableUpdateByPrimaryKeySelective = StringUtility
					.isTrue(enableUpdateByPrimaryKeySelective);
		if (StringUtility.stringHasValue(enableUpdateByExample))
			this.enableUpdateByExample = StringUtility
					.isTrue(enableUpdateByExample);
		if (StringUtility.stringHasValue(enableBatchUpdateByExample))
			this.enableBatchUpdateByExample = StringUtility
					.isTrue(enableBatchUpdateByExample);

		return true;
	}

	@Override
	public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(
			IntrospectedTable introspectedTable) {
		List<GeneratedJavaFile> files = new ArrayList<GeneratedJavaFile>();
		String table = introspectedTable.getBaseRecordType();
		String tableName = table.replaceAll(this.pojoUrl + ".", "");

		serviceType = new FullyQualifiedJavaType(servicePack + "." + tableName
				+ "Service");
		serviceName = toLowerCase(tableName + "Service");
		testType = new FullyQualifiedJavaType(targetPackage + ".base.test."
				+ targetModel + "." + tableName + "Test");

		pojoType = new FullyQualifiedJavaType(pojoUrl + "." + tableName);

		qoType = new FullyQualifiedJavaType(introspectedTable
				.getBaseRecordType().replace(".po.", ".qo.") + "Qo");
		boType = new FullyQualifiedJavaType(introspectedTable
				.getBaseRecordType().replace(".po.", ".bo.") + "Bo");

		TopLevelClass topLevelClass = new TopLevelClass(testType);

		// 导入必要的类
		addImport(topLevelClass);

		// 实现类
		addTest(topLevelClass, introspectedTable, tableName, files);

		return files;
	}

	/**
	 * 添加实现类
	 * 
	 * @param introspectedTable
	 * @param tableName
	 * @param files
	 */
	protected void addTest(TopLevelClass topLevelClass,
			IntrospectedTable introspectedTable, String tableName,
			List<GeneratedJavaFile> files) {
		topLevelClass.setVisibility(JavaVisibility.PUBLIC);

		topLevelClass.addAnnotation("@RunWith(SpringJUnit4ClassRunner.class)");
		topLevelClass
				.addAnnotation("@ContextConfiguration(locations = \"classpath*:META-INF/spring/*.xml\")");
		topLevelClass
				.addAnnotation("@FixMethodOrder(MethodSorters.NAME_ASCENDING)");

		// 添加引用Service
		addField(topLevelClass, tableName);

		// 添加方法
		Method method = null;

		if (enableCount) {// 统计
			method = testCountByExample(introspectedTable, tableName);
			addMethodComment(method, "测试统计记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}
		if (enableSelectByPrimaryKey) {// 根据主键查询
			method = testSelectByPrimaryKey(introspectedTable, tableName);
			addMethodComment(method, "测试根据主键查询记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}

		// 根据条件查询-不分页
		if (enableSelectByExample) {
			method = testSelectByExample(introspectedTable, tableName);
			addMethodComment(method, "测试根据查询条件分页查询记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}
		// 分页查询-采用SQL分页
		if (enableSelectPageByExample) {
			method = testSelectPageByExample(introspectedTable, tableName);
			addMethodComment(method, "测试根据查询条件分页查询记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}

		// 根据条件查询所有记录
		if (enableSelectAllByExample) {
			method = testSelectAllByExample(introspectedTable, tableName);
			addMethodComment(method, "测试查询所有记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}

		// 查询所有简单记录
		if (enableSelectSimpleByExample) {
			method = testSelectSimpleByExample(introspectedTable, tableName);
			addMethodComment(method, "测试查询所有简单记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}

		// 校验是否唯一
		if (enableIsUniqueByExample) {
			method = testIsUniqueByExample(introspectedTable, tableName);
			addMethodComment(method, "测试查询记录是否唯一");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}
		if (enableInsert) {
			method = testInsert(introspectedTable, tableName);
			addMethodComment(method, "测试添加记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}
		if (enableInsertSelective) {
			method = testInsertSelective(introspectedTable, tableName);
			addMethodComment(method, "测试添加记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}

		if (enableUpdateByPrimaryKey) {
			method = testUpdateByPrimaryKey(introspectedTable, tableName);
			addMethodComment(method, "测试根据主键修改记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}

		if (enableUpdateByPrimaryKeySelective) {
			method = testUpdateByPrimaryKeySelective(introspectedTable,
					tableName);
			addMethodComment(method, "测试根据主键修改记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}

		if (enableUpdateByExampleSelective) {
			method = testUpdateByExampleSelective(introspectedTable, tableName);
			addMethodComment(method, "测试根据条件修改记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}

		if (enableUpdateByExample) {
			method = testUpdateByExample(introspectedTable, tableName);
			addMethodComment(method, "测试根据条件修改记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}
		// 批量修改
		if (enableBatchUpdateByExample) {
			method = testBatchUpdateByExample(introspectedTable, tableName);
			addMethodComment(method, "测试根据条件修改记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}
		
		
		if (enableDeleteByPrimaryKey) {
			method = testDeleteByKey(introspectedTable, tableName);
			addMethodComment(method, "测试根据主键删除记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}
		if (enableDeleteByExample) {
			method = testDeleteByExample(introspectedTable, tableName);
			addMethodComment(method, "测试根据根据删除记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}

		if (enableBatchDeleteByExample) {
			method = testBatchDelete(introspectedTable, tableName);
			addMethodComment(method, "测试批量删除记录");
			method.addAnnotation("@Test");
			topLevelClass.addMethod(method);
		}
		
		topLevelClass.addFileCommentLine(introspectedTable
				.getTableConfiguration().getTableName() + "Test");
		topLevelClass
				.addFileCommentLine(introspectedTable.getRemarks() + "测试类");
		addJavaFileComment(topLevelClass);

		// 生成文件
		GeneratedJavaFile file = new GeneratedJavaFile(topLevelClass, project);
		files.add(file);
	}

	/**
	 * 测试插入
	 * 
	 */
	protected Method testInsert(IntrospectedTable introspectedTable,
			String tableName) {
		Method method = new Method();
		method.setName("testInsert");
		method.setVisibility(JavaVisibility.PUBLIC);
		method.addBodyLine(tableName + "Bo record = new " + tableName + "Bo();");
		method.addBodyLine("for (int i = 0; i < 100; i++) {");
		method.addBodyLine("record = new " + tableName + "Bo();");

		setColumnValue(introspectedTable, method);

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("insert");
		sb.append("(");
		sb.append("record");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("}");
		method.addBodyLine("System.out.println(\"测试成功:insert\");");
		return method;
	}

	/**
	 * 添加方法
	 * 
	 */
	protected Method testInsertSelective(IntrospectedTable introspectedTable,
			String tableName) {
		Method method = new Method();
		method.setName("testInsertSelective");
		method.setVisibility(JavaVisibility.PUBLIC);
		method.addBodyLine(tableName + "Bo record = new " + tableName + "Bo();");
		method.addBodyLine("for (int i = 0; i < 100; i++) {");
		method.addBodyLine("record = new " + tableName + "Bo();");

		setColumnValue(introspectedTable, method);

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("insertSelective");
		sb.append("(");
		sb.append("record");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("}");
		method.addBodyLine("System.out.println(\"测试成功:insertSelective\");");
		return method;
	}

	/**
	 * 添加方法
	 * 
	 */
	protected Method testUpdateByPrimaryKey(
			IntrospectedTable introspectedTable, String tableName) {
		Method method = new Method();
		method.setName("testUpdateByPrimaryKey");
		method.setVisibility(JavaVisibility.PUBLIC);
		method.addBodyLine(tableName + "Bo record = new " + tableName + "Bo();");

		setColumnValue(introspectedTable, method);

		method.addBodyLine("record.setId(1);");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("updateByPrimaryKey");
		sb.append("(");
		sb.append("record");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:updateByPrimaryKey\");");
		return method;
	}

	/**
	 * 添加方法
	 * 
	 */
	protected Method testUpdateByPrimaryKeySelective(
			IntrospectedTable introspectedTable, String tableName) {
		Method method = new Method();
		method.setName("testUpdateByPrimaryKeySelective");
		method.setVisibility(JavaVisibility.PUBLIC);
		method.addBodyLine(tableName + "Bo record = new " + tableName + "Bo();");

		setColumnValue(introspectedTable, method);

		method.addBodyLine("record.setId(1);");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("updateByPrimaryKeySelective");
		sb.append("(");
		sb.append("record");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:updateByPrimaryKeySelective\");");
		return method;
	}

	/**
	 * 添加方法
	 * 
	 */
	protected Method testUpdateByExampleSelective(
			IntrospectedTable introspectedTable, String tableName) {
		Method method = new Method();
		method.setName("testUpdateByExampleSelective");
		method.setVisibility(JavaVisibility.PUBLIC);
		method.addBodyLine(tableName + "Bo record = new " + tableName + "Bo();");
		method.addBodyLine(tableName + "Qo qo = new " + tableName + "Qo();");

		setColumnValue(introspectedTable, method);

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("updateBy" + tableName + "Selective");
		sb.append("(");
		sb.append("record,qo");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:updateBy" + tableName
				+ "Selective\");");
		return method;
	}

	/**
	 * 添加方法
	 * 
	 */
	protected Method testUpdateByExample(IntrospectedTable introspectedTable,
			String tableName) {
		Method method = new Method();
		method.setName("testUpdateByExampleSelective");
		method.setVisibility(JavaVisibility.PUBLIC);
		method.addBodyLine(tableName + "Bo record = new " + tableName + "Bo();");
		method.addBodyLine(tableName + "Qo qo = new " + tableName + "Qo();");

		setColumnValue(introspectedTable, method);

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("updateBy" + tableName);
		sb.append("(");
		sb.append("record,qo");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:updateBy" + tableName
				+ "\");");
		return method;
	}

	/**
	 * 添加测试统计记录方法
	 * 
	 */
	protected Method testCountByExample(IntrospectedTable introspectedTable,
			String tableName) {
		Method method = new Method();
		method.setName("testCountBy" + tableName);
		method.setVisibility(JavaVisibility.PUBLIC);

		method.addBodyLine(qoType.getShortName() + " qo = new "
				+ qoType.getShortName() + "();");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("countBy" + tableName);
		sb.append("(");
		sb.append("qo");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:countBy" + tableName
				+ "\");");
		return method;
	}

	/**
	 * 添加测试根据主键查询记录方法
	 * 
	 */
	protected Method testSelectByPrimaryKey(
			IntrospectedTable introspectedTable, String tableName) {
		Method method = new Method();
		method.setName("testSelectByPrimaryKey");
		method.setVisibility(JavaVisibility.PUBLIC);

		method.addBodyLine("int id = 1;");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("selectByPrimaryKey");
		sb.append("(");
		sb.append("id");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:selectByPrimaryKey\");");
		return method;
	}

	/**
	 * 添加测试查询所有记录方法
	 * 
	 */
	protected Method testSelectAllByExample(
			IntrospectedTable introspectedTable, String tableName) {
		Method method = new Method();
		method.setName("testSelectAllBy" + tableName);
		method.setVisibility(JavaVisibility.PUBLIC);

		method.addBodyLine(qoType.getShortName() + " qo = new "
				+ qoType.getShortName() + "();");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("selectAllBy" + tableName);
		sb.append("(");
		sb.append("qo");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:selectAllBy" + tableName
				+ "\");");
		return method;
	}

	/**
	 * 添加测试查询所有简单记录方法
	 * 
	 */
	protected Method testSelectSimpleByExample(
			IntrospectedTable introspectedTable, String tableName) {
		Method method = new Method();
		method.setName("testSelectSimpleBy" + tableName);
		method.setVisibility(JavaVisibility.PUBLIC);

		method.addBodyLine(qoType.getShortName() + " qo = new "
				+ qoType.getShortName() + "();");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("selectSimpleBy" + tableName);
		sb.append("(");
		sb.append("qo");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:testSelectSimpleBy"
				+ tableName + "\");");
		return method;
	}

	/**
	 * 添加测试查询记录是否唯一方法
	 * 
	 */
	protected Method testIsUniqueByExample(IntrospectedTable introspectedTable,
			String tableName) {
		Method method = new Method();
		method.setName("testIsUniqueBy" + tableName);
		method.setVisibility(JavaVisibility.PUBLIC);

		method.addBodyLine(qoType.getShortName() + " qo = new "
				+ qoType.getShortName() + "();");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("isUniqueBy" + tableName);
		sb.append("(");
		sb.append("qo");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:testIsUniqueBy"
				+ tableName + "\");");
		return method;
	}

	/**
	 * 添加测试根据查询条件分页查询记录方法
	 * 
	 */
	protected Method testSelectByExample(IntrospectedTable introspectedTable,
			String tableName) {
		Method method = new Method();
		method.setName("testSelectBy" + tableName);
		method.setVisibility(JavaVisibility.PUBLIC);
		method.addBodyLine(qoType.getShortName() + " qo = new "
				+ qoType.getShortName() + "();");
		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("selectBy" + tableName);
		sb.append("(");
		sb.append("qo");
		sb.append(");");
		method.addBodyLine(sb.toString());
		method.addBodyLine("System.out.println(\"测试成功:selectBy" + tableName
				+ "\");");
		return method;
	}

	/**
	 * 添加测试根据查询条件分页查询记录方法
	 * 
	 */
	protected Method testSelectPageByExample(
			IntrospectedTable introspectedTable, String tableName) {
		Method method = new Method();
		method.setName("testSelectPageBy" + tableName);
		method.setVisibility(JavaVisibility.PUBLIC);
		method.addBodyLine(qoType.getShortName() + " qo = new "
				+ qoType.getShortName() + "();");
		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("selectPageBy" + tableName);
		sb.append("(");
		sb.append("qo");
		sb.append(");");
		method.addBodyLine(sb.toString());
		method.addBodyLine("System.out.println(\"测试成功:selectPageBy" + tableName
				+ "\");");
		return method;
	}

	/**
	 * 添加测试批量删除记录方法
	 * 
	 */
	protected Method testBatchDelete(IntrospectedTable introspectedTable,
			String tableName) {
		Method method = new Method();
		method.setName("testBatchDelete");
		method.setVisibility(JavaVisibility.PUBLIC);

		method.addBodyLine("List<Integer> ids = new ArrayList<Integer>();");
		method.addBodyLine("for (int i = 1; i < 100; i++) {");
		method.addBodyLine("ids.add(i);");
		method.addBodyLine("}");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("batchDeleteBy" + tableName);
		sb.append("(");
		sb.append("ids");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:batchDeleteBy"
				+ tableName + "\");");
		return method;
	}

	/**
	 * 添加测试根据条件修改记录方法
	 * 
	 */
	protected Method testBatchUpdateByExample(
			IntrospectedTable introspectedTable, String tableName) {
		Method method = new Method();
		method.setName("testBatchUpdate");
		method.setVisibility(JavaVisibility.PUBLIC);

		method.addBodyLine("List<Integer> ids = new ArrayList<Integer>();");
		method.addBodyLine("for (int i = 1; i < 100; i++) {");
		method.addBodyLine("ids.add(i);");
		method.addBodyLine("}");

		method.addBodyLine(tableName + "Bo record = new " + tableName + "Bo();");
		setColumnValue(introspectedTable, method);

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("batchUpdateBy" + tableName);
		sb.append("(");
		sb.append("ids,record");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:batchUpdateBy"
				+ tableName + "\");");
		return method;
	}

	/**
	 * 添加测试根据主键删除记录方法
	 * 
	 */
	protected Method testDeleteByKey(IntrospectedTable introspectedTable,
			String tableName) {
		Method method = new Method();
		method.setName("testDeleteByKey");
		method.setVisibility(JavaVisibility.PUBLIC);

		method.addBodyLine("Integer id = 110;");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("deleteByPrimaryKey");
		sb.append("(");
		sb.append("id");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:deleteByPrimaryKey\");");
		return method;
	}

	/**
	 * 添加测试根据根据删除记录方法
	 * 
	 */
	protected Method testDeleteByExample(IntrospectedTable introspectedTable,
			String tableName) {
		Method method = new Method();
		method.setName("testDeleteBy" + tableName);
		method.setVisibility(JavaVisibility.PUBLIC);

		method.addBodyLine(qoType.getShortName() + " qo = new "
				+ qoType.getShortName() + "();");

		StringBuilder sb = new StringBuilder();
		sb = new StringBuilder();
		sb.append("this.");
		sb.append(getServiceShort());
		sb.append("deleteBy" + tableName);
		sb.append("(");
		sb.append("qo");
		sb.append(");");
		method.addBodyLine(sb.toString());

		method.addBodyLine("System.out.println(\"测试成功:deleteBy" + tableName
				+ "\");");
		return method;
	}

	/**
	 * 设置属性值
	 * 
	 * @param introspectedTable
	 * @param method
	 */
	protected void setColumnValue(IntrospectedTable introspectedTable,
			Method method) {
		List<IntrospectedColumn> baseColumns = introspectedTable
				.getBaseColumns();
		for (IntrospectedColumn column : baseColumns) {
			if (column.getFullyQualifiedJavaType().getShortName()
					.equals("String")) {
				method.addBodyLine("record.set"
						+ toUpperCase(column.getJavaProperty()) + "(\"测试\");");
			}
			if (column.getFullyQualifiedJavaType().getShortName()
					.equals("Date")) {
				method.addBodyLine("record.set"
						+ toUpperCase(column.getJavaProperty())
						+ "(new Date());");
			}
			if (column.getFullyQualifiedJavaType().getShortName()
					.equals("Integer")) {
				method.addBodyLine("record.set"
						+ toUpperCase(column.getJavaProperty()) + "(1);");
			}
			if (column.getFullyQualifiedJavaType().getShortName()
					.equals("Long")) {
				method.addBodyLine("record.set"
						+ toUpperCase(column.getJavaProperty()) + "(1l);");
			}

			if (column.getFullyQualifiedJavaType().getShortName()
					.equals("Float")) {
				method.addBodyLine("record.set"
						+ toUpperCase(column.getJavaProperty()) + "(1f);");
			}
			if (column.getFullyQualifiedJavaType().getShortName()
					.equals("Double")) {
				method.addBodyLine("record.set"
						+ toUpperCase(column.getJavaProperty()) + "(1d);");
			}

			if (column.getFullyQualifiedJavaType().getShortName()
					.equals("Boolen")) {
				method.addBodyLine("record.set"
						+ toUpperCase(column.getJavaProperty()) + "(true);");
			}

		}
	}

	protected void addComment(JavaElement field, String comment) {
		StringBuilder sb = new StringBuilder();
		field.addJavaDocLine("/**");
		sb.append(" * ");
		comment = comment.replaceAll(OutputUtilities.lineSeparator, "<br>"
				+ OutputUtilities.lineSeparator + "\t * ");
		sb.append(comment);
		field.addJavaDocLine(sb.toString());
		field.addJavaDocLine(" */");
	}

	/**
	 * 添加字段
	 * 
	 * @param topLevelClass
	 */
	protected void addField(TopLevelClass topLevelClass, String tableName) {
		// 添加 dao
		Field field = new Field();
		field.setName(serviceName); // 设置变量名
		topLevelClass.addImportedType(serviceType);
		field.setType(serviceType); // 类型
		field.setVisibility(JavaVisibility.PRIVATE);
		field.addAnnotation("@Autowired");
		topLevelClass.addField(field);
	}

	/**
	 * 添加字段
	 * 
	 * @param topLevelClass
	 */
	protected void addField(TopLevelClass topLevelClass) {
		// 添加 success
		Field field = new Field();
		field.setName("success"); // 设置变量名
		field.setType(FullyQualifiedJavaType.getBooleanPrimitiveInstance()); // 类型
		field.setVisibility(JavaVisibility.PRIVATE);
		addComment(field, "执行结果");
		topLevelClass.addField(field);
		// 设置结果
		field = new Field();
		field.setName("message"); // 设置变量名
		field.setType(FullyQualifiedJavaType.getStringInstance()); // 类型
		field.setVisibility(JavaVisibility.PRIVATE);
		addComment(field, "消息结果");
		topLevelClass.addField(field);
	}

	/**
	 * 添加方法
	 * 
	 */
	protected void addMethod(TopLevelClass topLevelClass) {
		Method method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("setSuccess");
		method.addParameter(new Parameter(FullyQualifiedJavaType
				.getBooleanPrimitiveInstance(), "success"));
		method.addBodyLine("this.success = success;");
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setReturnType(FullyQualifiedJavaType
				.getBooleanPrimitiveInstance());
		method.setName("isSuccess");
		method.addBodyLine("return success;");
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("setMessage");
		method.addParameter(new Parameter(FullyQualifiedJavaType
				.getStringInstance(), "message"));
		method.addBodyLine("this.message = message;");
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setReturnType(FullyQualifiedJavaType.getStringInstance());
		method.setName("getMessage");
		method.addBodyLine("return message;");
		topLevelClass.addMethod(method);
	}

	/**
	 * 添加方法
	 * 
	 */
	protected void addMethod(TopLevelClass topLevelClass, String tableName) {
		Method method2 = new Method();
		for (int i = 0; i < methods.size(); i++) {
			Method method = new Method();
			method2 = methods.get(i);
			method = method2;
			method.removeAllBodyLines();
			method.removeAnnotation();
			StringBuilder sb = new StringBuilder();
			sb.append("return this.");
			sb.append(getServiceShort());
			sb.append(method.getName());
			sb.append("(");
			List<Parameter> list = method.getParameters();
			for (int j = 0; j < list.size(); j++) {
				sb.append(list.get(j).getName());
				sb.append(",");
			}
			sb.setLength(sb.length() - 1);
			sb.append(");");
			method.addBodyLine(sb.toString());
			topLevelClass.addMethod(method);
		}
		methods.clear();
	}

	/**
	 * BaseUsers to baseUsers
	 * 
	 * @param tableName
	 * @return
	 */
	protected String toLowerCase(String tableName) {
		StringBuilder sb = new StringBuilder(tableName);
		sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
		return sb.toString();
	}

	/**
	 * BaseUsers to baseUsers
	 * 
	 * @param tableName
	 * @return
	 */
	protected String toUpperCase(String tableName) {
		StringBuilder sb = new StringBuilder(tableName);
		sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
		return sb.toString();
	}

	/**
	 * 导入需要的类
	 */
	private void addImport(TopLevelClass topLevelClass) {
		topLevelClass.addImportedType(qoType);
		topLevelClass.addImportedType(pojoType);
		topLevelClass.addImportedType(listType);
		topLevelClass.addImportedType(arrayListType);
		topLevelClass.addImportedType(dateType);
		topLevelClass.addImportedType(runWith);
		topLevelClass.addImportedType(methodSorters);
		topLevelClass.addImportedType(springJUnit4ClassRunner);
		topLevelClass.addImportedType(contextConfiguration);
		topLevelClass.addImportedType(fixMethodOrder);
		topLevelClass.addImportedType(boType);
		topLevelClass.addImportedType(test);
		topLevelClass.addImportedType(autowired);

	}

	private String getServiceShort() {
		return toLowerCase(serviceName) + ".";
	}

	public void addMethodComment(Method method, String comments) {

		StringBuilder sb = new StringBuilder();
		String remark = comments;
		if (remark != null && remark.length() != 0) {
			method.addJavaDocLine("/**"); //$NON-NLS-1$
			sb.append(" * "); //$NON-NLS-1$
			remark = remark.replaceAll(OutputUtilities.lineSeparator, "<br>"
					+ OutputUtilities.lineSeparator + "\t * ");
			sb.append(remark);
			method.addJavaDocLine(sb.toString());
			method.addJavaDocLine(" */"); //$NON-NLS-1$
		}
	}

	public void addMethodAnnotation(Method method) {
		method.addAnnotation("@Transactional()");
	}

	@Override
	public List<GeneratedJavaScriptFile> contextGenerateAdditionalJavaScriptFiles() {
		// TODO Auto-generated method stub
		List<GeneratedJavaScriptFile> files = new ArrayList<GeneratedJavaScriptFile>(
				1);
		return files;
	}

	@Override
	public List<GeneratedJavaScriptFile> contextGenerateAdditionalJavaScriptFiles(
			IntrospectedTable introspectedTable) {
		List<GeneratedJavaScriptFile> files = new ArrayList<GeneratedJavaScriptFile>(
				1);
		return files;
	}
	
	public void addJavaFileComment(CompilationUnit compilationUnit) {
		List<String> comments = compilationUnit.getFileCommentLines();
		String title = "";
		String description = "";
		if (comments != null && comments.size() == 1) {
			title = comments.get(0);
		} else if (comments != null && comments.size() == 2) {
			title = comments.get(0);
			description = comments.get(1);
		}
		compilationUnit.clearFileCommentLine();
		compilationUnit.addFileCommentLine("/**");
		compilationUnit.addFileCommentLine(" * Title:" + title + "<br>");
		compilationUnit.addFileCommentLine(" * Description:" + description
				+ "<br>");
		compilationUnit
				.addFileCommentLine(" * ");
		compilationUnit.addFileCommentLine(" * @Create:"
				+ DateUtils.format(new Date(), "yyyy-MM-dd") + "<br>");
		compilationUnit.addFileCommentLine(" * @author:super_dev_001<br>");
		compilationUnit.addFileCommentLine(" * @version: Object v1.0.0<br>");
		compilationUnit.addFileCommentLine(" * <br>");
		compilationUnit.addFileCommentLine(" * 修改历史:<br>");
		compilationUnit.addFileCommentLine(" * 修改人		修改日期		修改描述<br>");
		compilationUnit
				.addFileCommentLine(" * -----------------------------------<br>");
		compilationUnit.addFileCommentLine(" * <br>");
		compilationUnit.addFileCommentLine(" * <br>");
		compilationUnit.addFileCommentLine(" */");
		// add no file level comments by default
		return;
	}

}